﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using InspectionMAC.SystemThread;
using csLTDMC;
using InspectionMAC.Forms;

namespace InspectionMAC.Config
{
    public static class NGKickManager
    {
        private static readonly ConcurrentQueue<string> _ngMaterials = new ConcurrentQueue<string>();
        private static readonly object _syncRoot = new object();
        private static bool _lastSensorState = false;
        private static Timer _cleanupTimer;
        private const int CLEANUP_INTERVAL = 60000;

        // 最小触发间隔保护
        private static DateTime _lastKickTime = DateTime.Now;
        public static int MIN_KICK_INTERVAL_MS = 100;

        // 踢料处理状态标志
        private static bool _isKickProcessing = false;

        // DO控制状态检查
        private static bool _doInitialized = false;

        // 踢料确认相关
        private static readonly ConcurrentDictionary<string, DateTime> _pendingKickConfirmations =
            new ConcurrentDictionary<string, DateTime>();
        private static Timer _kickConfirmationTimer;
        private const int KICK_CONFIRMATION_CHECK_INTERVAL = 10;

        public static void Initialize()
        {
            // 检查DO控制库是否可用
            CheckDOControlAvailability();

            // 启动监控线程
            Thread sensorThread = new Thread(MonitorSensorWithQueue);
            sensorThread.IsBackground = true;
            sensorThread.Start();

            // 初始化清理定时器
            _cleanupTimer = new Timer(CleanupKickQueue, null, CLEANUP_INTERVAL, CLEANUP_INTERVAL);

            // 初始化踢料确认检查定时器
            _kickConfirmationTimer = new Timer(CheckKickConfirmations, null,
                KICK_CONFIRMATION_CHECK_INTERVAL, KICK_CONFIRMATION_CHECK_INTERVAL);

            Console.WriteLine($"NGKickManager初始化完成，最小触发间隔: {MIN_KICK_INTERVAL_MS}ms");
        }

        // 检查DO控制可用性
        private static void CheckDOControlAvailability()
        {
            try
            {
                // 测试DO控制
                int testValue = DIO_Thread.Do[10];
                Console.WriteLine($"DO控制库可用，DO[10]当前值: {testValue}");
                _doInitialized = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"DO控制库初始化失败: {ex.Message}");
                _doInitialized = false;
            }
        }

        [Obsolete("使用新的踢料队列逻辑，此方法已过时")]
        public static void AddNGMaterial(string materialId)
        {
            _ngMaterials.Enqueue(materialId);
            Console.WriteLine($"添加踢料物料: {materialId}, 当前队列: {_ngMaterials.Count}");
        }

        private static void MonitorSensorWithQueue()
        {
            Console.WriteLine("开始监控光纤传感器（使用踢料队列）...");

            while (true)
            {
                try
                {
                    // 获取当前传感器状态
                    bool currentState = DIO_Thread.Di[13] == 1;

                    // 记录传感器状态变化
                    if (currentState != _lastSensorState)
                    {
                        Console.WriteLine($"光纤传感器状态变化: {_lastSensorState} -> {currentState}");
                    }

                    // 检测上升沿（从0到1的变化）且不在踢料处理中
                    if (currentState && !_lastSensorState && !_isKickProcessing)
                    {
                        // 检查最小触发间隔
                        double timeSinceLastKick = (DateTime.Now - _lastKickTime).TotalMilliseconds;
                        if (timeSinceLastKick < MIN_KICK_INTERVAL_MS)
                        {
                            Console.WriteLine($"触发间隔过短({timeSinceLastKick:F0}ms < {MIN_KICK_INTERVAL_MS}ms)，忽略信号");
                            Thread.Sleep(10);
                            continue;
                        }

                        Console.WriteLine($"光纤传感器触发，时间间隔: {timeSinceLastKick:F0}ms");
                        Console.WriteLine($"当前踢料队列状态: {KickQueueManager.GetQueueStatus()}");

                        // 启动踢料处理
                        ThreadPool.QueueUserWorkItem(ProcessKickActionWithQueue);
                    }

                    _lastSensorState = currentState;
                    Thread.Sleep(5);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"监控光纤传感器异常: {ex.Message}");
                    Thread.Sleep(100);
                }
            }
        }

        // 使用踢料队列处理踢料动作
        private static void ProcessKickActionWithQueue(object state)
        {
            if (_isKickProcessing)
            {
                Console.WriteLine("已有踢料动作在处理中，忽略本次触发");
                return;
            }

            _isKickProcessing = true;

            try
            {
                double timeSinceLastKick = (DateTime.Now - _lastKickTime).TotalMilliseconds;
                if (timeSinceLastKick < MIN_KICK_INTERVAL_MS)
                {
                    Console.WriteLine($"二次检查：触发间隔过短({timeSinceLastKick:F0}ms)，取消踢料");
                    return;
                }

                // 获取当前在踢料传感器位置的物料（按完成时间排序）
                string materialId = GetCurrentMaterialAtKickSensor();

                if (materialId != null)
                {
                    // 验证物料状态
                    var material = MaterialTracker.GetMaterialInfo(materialId);
                    if (material != null && material.Status == MaterialTracker.MaterialStatus.WaitingForKickDecision)
                    {
                        Console.WriteLine($"检查物料状态: NeedKick={material.NeedKick}, IsKicked={material.IsKicked}, CompletionTime={material.CompletionTime:HH:mm:ss.fff}");

                        // 修复判断逻辑：只有需要踢料且未踢料的物料才执行踢料
                        if (material.NeedKick && !material.IsKicked)
                        {
                            Console.WriteLine($"执行踢料动作: 物料{materialId}, 创建时间: {material.CreationTime:HH:mm:ss.fff}");

                            // 执行踢料动作
                            if (ExecuteKickAction())
                            {
                                // 记录踢料时间，开始等待确认
                                _pendingKickConfirmations[materialId] = DateTime.Now;
                                Console.WriteLine($"踢料动作已执行，等待确认: 物料{materialId}");

                                _lastKickTime = DateTime.Now;
                            }
                            else
                            {
                                Console.WriteLine($"踢料动作执行失败: 物料{materialId}");
                            }
                        }
                        else
                        {
                            // 不需要踢料，正常通过
                            Console.WriteLine($"物料{materialId}不需要踢料，正常通过");
                            MaterialTracker.UpdateMaterialStatus(materialId, MaterialTracker.MaterialStatus.Completed);
                            BuilderManager.RemoveMaterialAfterKick(materialId);
                            _lastKickTime = DateTime.Now;
                        }
                    }
                    else
                    {
                        Console.WriteLine($"物料{materialId}状态不符合踢料条件或不存在，状态: {material?.Status}");
                        _lastKickTime = DateTime.Now;
                    }
                }
                else
                {
                    Console.WriteLine("光纤传感器触发，但未找到等待处理的物料");
                    Console.WriteLine($"当前踢料队列状态: {KickQueueManager.GetQueueStatus()}");
                    _lastKickTime = DateTime.Now;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理踢料动作异常: {ex.Message}");
            }
            finally
            {
                _isKickProcessing = false;
            }
        }

        // 踢料确认检查
        private static void CheckKickConfirmations(object state)
        {
            try
            {
                DateTime now = DateTime.Now;
                var confirmedKicks = new List<string>();
                var failedKicks = new List<string>();

                // 检查所有待确认的踢料
                foreach (var kvp in _pendingKickConfirmations)
                {
                    string materialId = kvp.Key;
                    DateTime kickTime = kvp.Value;

                    // 检查是否超时（150ms）
                    if ((now - kickTime).TotalMilliseconds > 150)
                    {
                        failedKicks.Add(materialId);
                        continue;
                    }

                    // 检查DI5确认信号
                    if (DIO_Thread.Di[5] == 1)
                    {
                        confirmedKicks.Add(materialId);
                        Console.WriteLine($"踢料确认成功: 物料{materialId}, 耗时: {(now - kickTime).TotalMilliseconds:F0}ms");
                    }
                }

                // 处理确认成功的踢料
                foreach (string materialId in confirmedKicks)
                {
                    HandleKickConfirmation(materialId, true);
                    _pendingKickConfirmations.TryRemove(materialId, out _);
                }

                // 处理确认失败的踢料
                foreach (string materialId in failedKicks)
                {
                    HandleKickConfirmation(materialId, false);
                    _pendingKickConfirmations.TryRemove(materialId, out _);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"检查踢料确认异常: {ex.Message}");
            }
        }

        // 处理踢料确认结果
        private static void HandleKickConfirmation(string materialId, bool success)
        {
            try
            {
                if (!success)
                {
                    // 踢料失败确认：只需要设置DO8=1
                    TriggerKickFailureAlarm();
                    Console.WriteLine($"踢料失败确认: 物料{materialId}, 已设置DO8=1");
                }
                else
                {
                    Console.WriteLine($"踢料确认成功: 物料{materialId}");
                }

                // 无论成功与否，都正常完成物料处理
                var material = MaterialTracker.GetMaterialInfo(materialId);
                if (material != null)
                {
                    MaterialTracker.SetKickInfo(materialId, true, success);
                    MaterialTracker.UpdateMaterialStatus(materialId,
                        success ? MaterialTracker.MaterialStatus.Kicked : MaterialTracker.MaterialStatus.Completed);

                    KickQueueManager.RemoveFromKickQueue(materialId);
                    BuilderManager.RemoveMaterialAfterKick(materialId);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理踢料确认异常: {ex.Message}");
            }
        }

        // 踢料失败报警（设置DO8=1）
        private static void TriggerKickFailureAlarm()
        {
            if(!MacTestForm.macTestForm.isKickConfirm)
            {
                Console.WriteLine("未开启踢料确认");
                return;
            }
            try
            {
                DIO_Thread.Do[8] = 1;
                MacTestForm.macTestForm.Invoke(new Action(() =>
                {
                    MacTestForm.macTestForm.ShowAlarmForm("踢料失败！");
                    MacTestForm.macTestForm.AddLog("踢料失败！");
                }));
                Console.WriteLine($"踢料失败报警: 设置DO8=1");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"触发踢料失败报警异常: {ex.Message}");
            }
        }

        // 获取当前在踢料传感器位置的物料（按完成时间排序）
        private static string GetCurrentMaterialAtKickSensor()
        {
            // 获取所有等待踢料判断的物料，按完成时间排序（最早完成的优先）
            var waitingMaterial = MaterialTracker.GetNextWaitingForKickMaterial();
            if (waitingMaterial != null)
            {
                Console.WriteLine($"找到等待踢料判断的物料: {waitingMaterial.Id}, 完成时间: {waitingMaterial.CompletionTime:HH:mm:ss.fff}");
                return waitingMaterial.Id;
            }

            Console.WriteLine("未找到等待踢料判断的物料");
            return null;
        }

        // 执行踢料动作
        private static bool ExecuteKickAction()
        {
            if (!_doInitialized)
            {
                Console.WriteLine("DO控制库未初始化，无法执行踢料动作");
                return false;
            }

            try
            {
                Console.WriteLine($"踢料前DO状态: DIO_Thread.Do[10] = {DIO_Thread.Do[10]}");

                // 快速执行踢料动作，不等待确认
                DIO_Thread.Do[10] = 1;
                Console.WriteLine($"设置DO[10] = 1, 实际值: {DIO_Thread.Do[10]}");

                // 使用异步方式保持踢料状态
                ThreadPool.QueueUserWorkItem(state =>
                {
                    try
                    {
                        int kickDuration = MacTestForm.macTestForm.Kick_ms;
                        Console.WriteLine($"踢料持续时间: {kickDuration}ms");
                        Thread.Sleep(kickDuration);
                        DIO_Thread.Do[10] = 0;
                        Console.WriteLine($"踢料动作完成，DO[10]恢复为0");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"踢料保持异常: {ex.Message}");
                        try { DIO_Thread.Do[10] = 0; } catch { }
                    }
                });

                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"踢料DO控制异常: {ex.Message}");
                // 确保DO恢复为0
                try { DIO_Thread.Do[10] = 0; } catch { }
                return false;
            }
        }

        // 检查DO状态
        public static string CheckDOStatus()
        {
            try
            {
                return $"DO[10]状态: {DIO_Thread.Do[10]}, DO[8]状态: {DIO_Thread.Do[8]}, 最后踢料时间: {_lastKickTime:HH:mm:ss.fff}, DO控制库初始化: {_doInitialized}";
            }
            catch (Exception ex)
            {
                return $"检查DO状态异常: {ex.Message}";
            }
        }

        // 手动触发踢料测试
        public static void ManualKickTest()
        {
            Console.WriteLine("=== 手动踢料测试 ===");
            Console.WriteLine($"当前DO[10]状态: {DIO_Thread.Do[10]}");

            try
            {
                // 测试DO控制
                DIO_Thread.Do[10] = 1;
                Console.WriteLine($"设置DO[10] = 1, 实际值: {DIO_Thread.Do[10]}");
                Thread.Sleep(100);
                DIO_Thread.Do[10] = 0;
                Console.WriteLine($"设置DO[10] = 0, 实际值: {DIO_Thread.Do[10]}");
                Console.WriteLine("手动踢料测试完成");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"手动踢料测试异常: {ex.Message}");
            }
        }

        // 清理踢料队列
        private static void CleanupKickQueue(object state)
        {
            try
            {
                int currentCount = _ngMaterials.Count;
                if (currentCount > 0)
                {
                    Console.WriteLine($"清理旧踢料队列 [当前数量: {currentCount}]");
                    while (_ngMaterials.TryDequeue(out _)) { }
                }

                // 同时清理新踢料队列中的异常物料
                var queueSnapshot = KickQueueManager.GetQueueSnapshot();
                if (queueSnapshot.Count > 0)
                {
                    Console.WriteLine($"检查踢料队列状态: {queueSnapshot.Count}个物料");
                    foreach (var materialId in queueSnapshot)
                    {
                        var material = MaterialTracker.GetMaterialInfo(materialId);
                        if (material == null || material.IsKicked || material.Status == MaterialTracker.MaterialStatus.Completed)
                        {
                            KickQueueManager.RemoveFromKickQueue(materialId);
                            Console.WriteLine($"清理无效物料: {materialId}");
                        }
                    }
                }

                // 清理过期的待确认踢料（超过300ms）
                DateTime now = DateTime.Now;
                var expiredConfirmations = new List<string>();
                foreach (var kvp in _pendingKickConfirmations)
                {
                    if ((now - kvp.Value).TotalMilliseconds > 300)
                    {
                        expiredConfirmations.Add(kvp.Key);
                    }
                }
                foreach (string materialId in expiredConfirmations)
                {
                    _pendingKickConfirmations.TryRemove(materialId, out _);
                    Console.WriteLine($"清理过期踢料确认: {materialId}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"清理踢料队列异常: {ex.Message}");
            }
        }

        // 获取踢料队列状态信息
        public static string GetKickQueueInfo()
        {
            var queueSnapshot = KickQueueManager.GetQueueSnapshot();
            var waitingMaterials = MaterialTracker.GetAllActiveMaterials()
                .Where(m => m.Status == MaterialTracker.MaterialStatus.WaitingForKickDecision)
                .OrderBy(m => m.CompletionTime)
                .ToList();

            return $"踢料队列: {queueSnapshot.Count}个物料, 等待判断: {waitingMaterials.Count}个物料, 待确认踢料: {_pendingKickConfirmations.Count}个, 下次触发间隔: {Math.Max(0, MIN_KICK_INTERVAL_MS - (DateTime.Now - _lastKickTime).TotalMilliseconds):F0}ms";
        }

        // 强制踢料（用于测试）
        public static void ForceKick(string materialId)
        {
            try
            {
                Console.WriteLine($"强制踢料: {materialId}");
                if (ExecuteKickAction())
                {
                    MaterialTracker.SetKickInfo(materialId, true, true);
                    MaterialTracker.UpdateMaterialStatus(materialId, MaterialTracker.MaterialStatus.Kicked);
                    KickQueueManager.RemoveFromKickQueue(materialId);
                    BuilderManager.RemoveMaterialAfterKick(materialId);
                    Console.WriteLine($"强制踢料完成: {materialId}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"强制踢料异常: {ex.Message}");
            }
        }
    }
}